/**
 * @file    gt98xx_drv_timer.h
 * @author  Giantec-Semi ATE
 * @brief   Header file of TIMER driver module.
 * @version 0.1
 * 
 * @copyright Copyright (c) 2021 Giantec-Semi
 * 
 */

#ifndef GT98XX_DRIVER_GT98XX_DRV_TIMER_H_
#define GT98XX_DRIVER_GT98XX_DRV_TIMER_H_

#ifdef __cplusplus
  extern "C" {
#endif /* __cplusplus */

#include "gt98xx_drv_def.h"
#include "gt98xx_drv_conf.h"

/**
 * @addtogroup GT9881_Drivers
 * @{
 */

/**
 * @defgroup TIMER_DRV TIMER Drivers
 * @{
 */

/**
 * @defgroup TIMER_DRV_Exported_Types TIMER Drivers Exported Types
 * @{
 */

/**
 * @struct DrvTimerInitTypedef
 * @brief TIMER drivers init structure definition
 */
typedef struct tagDrvTimerInitTypedef {
  uint32_t load_value;          ///< Timer Load Value 
  uint32_t timer_count_dir;     ///< Timer Count Up/Down 
  uint32_t auto_load;           ///< Timer Auto Load 
  uint32_t mode;                ///< Timer Mode 
} DrvTimerInitTypedef;
/** @} TIMER_DRV_Exported_Types */

/**
 * @defgroup TIMER_DRV_Exported_Constants TIMER Drivers Exported Constants
 * @{
 */

/**
 * @defgroup TIMER_DRV_EC_ClkDiv Clock Division Control
 * @{
 */
#define DRV_TIMER_CLK_DIV_2                ((2-1) << TMR_CONTROL_CLK_DIV_Pos)         ///< Timer clock divisor 2
#define DRV_TIMER_CLK_DIV_32               ((32-1) << TMR_CONTROL_CLK_DIV_Pos)        ///< Timer clock divisor 32
#define DRV_TIMER_CLK_DIV_256              ((256-1) << TMR_CONTROL_CLK_DIV_Pos)       ///< Timer clock divisor 256
#define DRV_TIMER_CLK_DIV_2048             ((2048-1) << TMR_CONTROL_CLK_DIV_Pos)      ///< Timer clock divisor 2048
/** @} UART_DRV_EC_ClkDiv */

/**
 * @defgroup TIMER_DRV_EC_Count Count Control
 * @{
 */
#define DRV_TIMER_COUNT_UP                 ((0x0U) << TMR_CONTROL_UP_DWN_Pos)                ///< Timer count up
#define DRV_TIMER_COUNT_DOWN               ((0x1U) << TMR_CONTROL_UP_DWN_Pos)   ///< Timer count down
/** @} TIMER_DRV_EC_DataWidth */

/**
 * @defgroup TIMER_DRV_EC_AutoLoad Auto Load Control
 * @{
 */
#define DRV_TIMER_ONE_SHOT                 ((0x0U) << TMR_CONTROL_AUTO_LD_Pos)                 ///< Timer one shot
#define DRV_TIMER_AUTO_LD                  ((0x1U) << TMR_CONTROL_AUTO_LD_Pos)     ///< Timer auto load
/** @} TIMER_DRV_EC_AutoLoad */

/**
 * @defgroup TIMER_DRV_EC_Capture Capture Control
 * @{
 */
#define DRV_TIMER_CAP_FIRST                ((0x0U) << TMR_CONTROL_CAP_MODE_Pos)                 ///< Timer capture first valid
#define DRV_TIMER_CAP_SECOND               ((0x1U) << TMR_CONTROL_CAP_MODE_Pos)   ///< Timer capture second valid
/** @} TIMER_DRV_EC_Capture */

/**
 * @defgroup TIMER_DRV_EC_CaptureEvent Capture Event Control
 * @{
 */
#define DRV_TIMER_CAP_DIS                  ((0x0U) << TMR_CONTROL_CAP_EVENT_Pos)   ///< Timer capture mode disable
#define DRV_TIMER_CAP_H2L                  ((0x1U) << TMR_CONTROL_CAP_EVENT_Pos)   ///< Timer capture high to low edge
#define DRV_TIMER_CAP_L2H                  ((0x2U) << TMR_CONTROL_CAP_EVENT_Pos)   ///< Timer capture low to high edge
#define DRV_TIMER_CAP_BOTH                 ((0x3U) << TMR_CONTROL_CAP_EVENT_Pos)   ///< Timer capture both edge
/** @} TIMER_DRV_EC_CaptureEvent */

/**
 * @defgroup TIMER_DRV_EC_TimerMod Timer Mode Control
 * @{
 */
#define DRV_TIMER_FREE_RUN                 ((0x0U) << TMR_CONTROL_MODE_Pos)             ///< Timer free run mode
#define DRV_TIMER_USER_DEF                 ((0x1U) << TMR_CONTROL_MODE_Pos)   ///< Timer user define mode
/** @} TIMER_DRV_EC_TimerMod */

/**
 * @defgroup TIMER_DRV_EC_TimerTrigger Timer Trigger Control
 * @{
 */
#define DRV_TIMER_NO_TRI                   ((0x0U) << TMR_CONTROL_PWM_TRG_Pos)   ///< Timer no pwm trigger
#define DRV_TIMER_OF                       ((0x1U) << TMR_CONTROL_PWM_TRG_Pos)   ///< Timer pwm trigger for overflow mode
#define DRV_TIMER_OF_MAT                   ((0x2U) << TMR_CONTROL_PWM_TRG_Pos)   ///< Timer pwm trigger for overflow and match mode
#define DRV_TIMER_MAT                      ((0x3U) << TMR_CONTROL_PWM_TRG_Pos)   ///< Timer pwm trigger for match mode
/** @} TIMER_DRV_EC_TimerTrigger */

/**
 * @defgroup TIMER_DRV_EC_PwmOut PWM Out Control
 * @{
 */
#define DRV_TIMER_OUT_PLU                  ((0x0U) << TMR_CONTROL_PULSE_TGL_Pos)                  ///< Timer pwm pluse
#define DRV_TIMER_OUT_TOG                  ((0x1U) << TMR_CONTROL_PULSE_TGL_Pos)   ///< Timer pwm toggle
/** @} TIMER_DRV_EC_PwmOut */

/**
 * @defgroup TIMER_DRV_EC_PwmPluse PWM Pluse Control
 * @{
 */
#define DRV_TIMER_POS                      ((0x0U) << TMR_CONTROL_PWM_POL_Pos)                ///< Timer pwm positive
#define DRV_TIMER_NEG                      ((0x1U) << TMR_CONTROL_PWM_POL_Pos)   ///< Timer pwm negative
/** @} TIMER_DRV_EC_PwmPluse */

/** @} TIMER_DRV_Exported_Constants */

/**
 * @defgroup TIMER_DRV_Exported_Macros TIMER Drivers Exported Macros
 * @{
 */

/** @} TIMER_DRV_Exported_Macros */

/**
 * @defgroup TIMER_DRV_Exported_Functions TIMER Drivers Exported Functions
 * @{
 */

/**
 * @defgroup TIMER_DRV_EF_Configuration TIMER Configuration Exported Functions
 * @{
 */

/**
 * @fn __STATIC_INLINE void DrvTimerLoad(TimerTypedef* timer_instance)
 * @brief Write to trigger load TMRn_LOAD_VALUE into timer n and clear clock pre-scale counter
 * 
 * @param[in] timer_instance Timer instance
 */
__STATIC_INLINE void DrvTimerLoad(TimerTypedef* timer_instance) {
  SET_BIT(timer_instance->LOAD, TMR_LOAD);
}

/**
 * @fn __STATIC_INLINE void DrvTimerSetValue(TimerTypedef* timer_instance, uint32_t value)
 * @brief Set value to be loaded into TIMERn
 * 
 * @param[in] timer_instance Timer instance
 * @param[in] value Timer Value
 */
__STATIC_INLINE void DrvTimerSetValue(TimerTypedef* timer_instance, uint32_t value) {
  WRITE_REG(timer_instance->LOAD_VALUE, value);
}

/**
 * @fn __STATIC_INLINE uint32_t DrvTimerGetValue(TimerTypedef* timer_instance)
 * @brief Get value loaded in TIMERn
 * 
 * @param[in] timer_instance Timer instance
 * @return Timer Value
 */
__STATIC_INLINE uint32_t DrvTimerGetValue(TimerTypedef* timer_instance) {
  return (uint32_t)READ_REG(timer_instance->COUNT);
}

/**
 * @fn __STATIC_INLINE uint32_t DrvTimerGetCap1Value(TimerTypedef* timer_instance)
 * @brief Get capture value1
 * 
 * @param[in] timer_instance Timer instance
 * @return Timer Value
 */
__STATIC_INLINE uint32_t DrvTimerGetCap1Value(TimerTypedef* timer_instance) {
  return (uint32_t)READ_REG(timer_instance->CAP1_VALUE);
}

/**
 * @fn __STATIC_INLINE uint32_t DrvTimerGetCap2Value(TimerTypedef* timer_instance)
 * @brief Get capture value2
 * 
 * @param[in] timer_instance Timer instance
 * @return Timer Value
 */
__STATIC_INLINE uint32_t DrvTimerGetCap2Value(TimerTypedef* timer_instance) {
  return (uint32_t)READ_REG(timer_instance->CAP2_VALUE);
}

/**
 * @fn __STATIC_INLINE uint32_t DrvTimerGetMatValue(TimerTypedef* timer_instance)
 * @brief Get match value
 * 
 * @param[in] timer_instance Timer instance
 * @return Timer Value 
 */
__STATIC_INLINE uint32_t DrvTimerGetMatValue(TimerTypedef* timer_instance) {
  return (uint32_t)READ_REG(timer_instance->COMP_VALUE);
}

/**
 * @fn __STATIC_INLINE uint32_t DrvTimerSetMatValue(TimerTypedef* timer_instance, uint32_t value)
 * @brief Set match value
 * 
 * @param[in] timer_instance Timer instance
 * @param[in] value TIMER compare value
 */
__STATIC_INLINE void DrvTimerSetMatValue(TimerTypedef* timer_instance, uint32_t value) {
  WRITE_REG(timer_instance->COMP_VALUE, value);
}

/**
 * @fn __STATIC_INLINE uint32_t DrvTimerSetCurValue(TimerTypedef* timer_instance, uint32_t value)
 * @brief Set value loaded in TIMERn
 * 
 * @param[in] timer_instance Timer instance
 * @param[in] value Timer Value
 */
__STATIC_INLINE uint32_t DrvTimerSetCurValue(TimerTypedef* timer_instance, uint32_t value) {
  return (uint32_t)WRITE_REG(timer_instance->COUNT, value);
}

/**
 * @fn __STATIC_INLINE void DrvTimerSetDivision(TimerTypedef* timer_instance, uint32_t division)
 * @brief Set divisor for clock pre-scaler
 * 
 * @param[in] timer_instance Timer instance
 * @param[in] division This parameter can be one of the following values:
 *            @arg @ref DRV_TIMER_CLK_DIV_2
 *            @arg @ref DRV_TIMER_CLK_DIV_32
 *            @arg @ref DRV_TIMER_CLK_DIV_256
 *            @arg @ref DRV_TIMER_CLK_DIV_2048
 */
__STATIC_INLINE void DrvTimerSetDivision(TimerTypedef* timer_instance, uint32_t division) {
  MODIFY_REG(timer_instance->CONTROL, TMR_CONTROL_CLK_DIV, division);
}

/**
 * @fn __STATIC_INLINE uint32_t DrvTimerGetDivision(TimerTypedef* timer_instance)
 * @brief Get divisor for clock pre-scaler
 * 
 * @param[in] timer_instance Timer instance
 * @return Division
 * @retval DRV_TIMER_CLK_DIV_2
 * @retval DRV_TIMER_CLK_DIV_32
 * @retval DRV_TIMER_CLK_DIV_256
 * @retval DRV_TIMER_CLK_DIV_2048
 */
__STATIC_INLINE uint32_t DrvTimerGetDivision(TimerTypedef* timer_instance) {
  return (uint32_t)READ_BIT(timer_instance->CONTROL, TMR_CONTROL_CLK_DIV);
}

/**
 * @fn __STATIC_INLINE void DrvTimerSetCountMode(TimerTypedef* timer_instance, uint32_t count_mode)
 * @brief Set timer counting mode
 * 
 * @param[in] timer_instance Timer instance
 * @param[in] count_mode This parameter can be one of the following values:
 *            @arg @ref DRV_TIMER_COUNT_UP
 *            @arg @ref DRV_TIMER_COUNT_DOWN
 */
__STATIC_INLINE void DrvTimerSetCountMode(TimerTypedef* timer_instance, uint32_t count_mode) {
  MODIFY_REG(timer_instance->CONTROL, TMR_CONTROL_UP_DWN, count_mode);
}

/**
 * @fn __STATIC_INLINE uint32_t DrvTimerGetCountMode(TimerTypedef* timer_instance)
 * @brief Get timer counting mode
 * 
 * @param[in] timer_instance Timer instance
 * @return Timer counting mode
 * @retval DRV_TIMER_COUNT_UP
 * @retval DRV_TIMER_COUNT_DOWN
 */
__STATIC_INLINE uint32_t DrvTimerGetCountMode(TimerTypedef* timer_instance) {
  return (uint32_t)READ_BIT(timer_instance->CONTROL, TMR_CONTROL_UP_DWN);
}

/**
 * @fn __STATIC_INLINE void DrvTimerSetLdMode(TimerTypedef* timer_instance, uint32_t auto_ld)
 * @brief Set timer counter mode
 * 
 * @param[in] timer_instance Timer instance
 * @param[in] auto_ld This parameter can be one of the following values:
 *            @arg @ref DRV_TIMER_ONE_SHOT
 *            @arg @ref DRV_TIMER_AUTO_LD
 */
__STATIC_INLINE void DrvTimerSetLdMode(TimerTypedef* timer_instance, uint32_t auto_ld) {
  MODIFY_REG(timer_instance->CONTROL, TMR_CONTROL_AUTO_LD, auto_ld);
}

/**
 * @fn __STATIC_INLINE uint32_t DrvTimerGetLdMode(TimerTypedef* timer_instance)
 * @brief Get timer counter mode
 * 
 * @param[in] timer_instance Timer instance
 * @return Timer counter mode
 * @retval DRV_TIMER_ONE_SHOT
 * @retval DRV_TIMER_AUTO_LD
 */
__STATIC_INLINE uint32_t DrvTimerGetLdMode(TimerTypedef* timer_instance) {
  return (uint32_t)READ_BIT(timer_instance->CONTROL, TMR_CONTROL_AUTO_LD);
}

/**
 * @fn __STATIC_INLINE void DrvTimerEnableRes(TimerTypedef* timer_instance)
 * @brief Enable timer software reset
 * 
 * @param[in] timer_instance Timer instance
 */
__STATIC_INLINE void DrvTimerEnableRes(TimerTypedef* timer_instance) {
  SET_BIT(timer_instance->CONTROL, TMR_CONTROL_SRST);
}

/**
 * @fn __STATIC_INLINE void DrvTimerDisableRes(TimerTypedef* timer_instance)
 * @brief Disable timer software reset
 * 
 * @param[in] timer_instance Timer instance
 */
__STATIC_INLINE void DrvTimerDisableRes(TimerTypedef* timer_instance) {
  CLEAR_BIT(timer_instance->CONTROL, TMR_CONTROL_SRST);
}

/**
 * @fn __STATIC_INLINE uint32_t DrvTimerIsEnabledRes(TimerTypedef* timer_instance)
 * @brief Timer software reset is enabled
 * 
 * @param[in] timer_instance Timer instance
 * @return status:
 * @retval 1 Enable
 * @retval 0 Disable
 */
__STATIC_INLINE uint32_t DrvTimerIsEnabledRes(TimerTypedef* timer_instance) {
  return (uint32_t)(READ_BIT(timer_instance->CONTROL, TMR_CONTROL_SRST) >> TMR_CONTROL_SRST_Pos);
}

/**
 * @fn __STATIC_INLINE void DrvTimerEnableCom(TimerTypedef* timer_instance)
 * @brief Enable timer compare mode
 * 
 * @param[in] timer_instance Timer instance
 */
__STATIC_INLINE void DrvTimerEnableCom(TimerTypedef* timer_instance) {
  SET_BIT(timer_instance->CONTROL, TMR_CONTROL_COMP_EN);
}

/**
 * @fn __STATIC_INLINE void DrvTimerDisableCom(TimerTypedef* timer_instance)
 * @brief Disable timer compare mode
 * 
 * @param[in] timer_instance Timer instance
 */
__STATIC_INLINE void DrvTimerDisableCom(TimerTypedef* timer_instance) {
  CLEAR_BIT(timer_instance->CONTROL, TMR_CONTROL_COMP_EN);
}

/**
 * @fn __STATIC_INLINE uint32_t DrvTimerIsEnabledCom(TimerTypedef* timer_instance)
 * @brief Timer compare mode is enabled
 * 
 * @param[in] timer_instance Timer instance
 * @return status:
 * @retval 1 Enable
 * @retval 0 Disable
 */
__STATIC_INLINE uint32_t DrvTimerIsEnabledCom(TimerTypedef* timer_instance) {
  return (uint32_t)(READ_BIT(timer_instance->CONTROL, TMR_CONTROL_COMP_EN) >> TMR_CONTROL_COMP_EN_Pos);
}


/**
 * @fn __STATIC_INLINE void DrvTimerSetCapMode(TimerTypedef* timer_instance, uint32_t cap_mode)
 * @brief Set capture mode
 * 
 * @param[in] timer_instance Timer instance
 * @param[in] cap_mode This parameter can be one of the following values:
 *        @arg @ref DRV_TIMER_CAP_FIRST
 *        @arg @ref DRV_TIMER_CAP_SECOND
 */
__STATIC_INLINE void DrvTimerSetCapMode(TimerTypedef* timer_instance, uint32_t cap_mode) {
  MODIFY_REG(timer_instance->CONTROL, TMR_CONTROL_CAP_MODE, cap_mode);
}

/**
 * @fn __STATIC_INLINE uint32_t DrvTimerGetCapMode(TimerTypedef* timer_instance)
 * @brief Get capture mode
 * 
 * @param[in] timer_instance Timer instance
 * @return capture mode can be one of the following values:
 * @retval DRV_TIMER_CAP_FIRST
 * @retval DRV_TIMER_CAP_SECOND
 */
__STATIC_INLINE uint32_t DrvTimerGetCapMode(TimerTypedef* timer_instance) {
  return (uint32_t)READ_BIT(timer_instance->CONTROL, TMR_CONTROL_CAP_MODE);
}

/**
 * @fn __STATIC_INLINE void DrvTimerSetCapEve(TimerTypedef* timer_instance, uint32_t event)
 * @brief Set capture event
 * 
 * @param[in] timer_instance Timer instance
 * @param[in] event This parameter can be one of the following values:
 *            @arg @ref DRV_TIMER_CAP_DIS
 *            @arg @ref DRV_TIMER_CAP_H2L
 *            @arg @ref DRV_TIMER_CAP_L2H
 *            @arg @ref DRV_TIMER_CAP_BOTH
 */
__STATIC_INLINE void DrvTimerSetCapEve(TimerTypedef* timer_instance, uint32_t event) {
  MODIFY_REG(timer_instance->CONTROL, TMR_CONTROL_CAP_EVENT, event);
}

/**
 * @fn __STATIC_INLINE uint32_t DrvTimerGetCapEve(TimerTypedef* timer_instance)
 * @brief Get capture event
 * 
 * @param[in] timer_instance Timer instance
 * @return Event can be one of the following values:
 * @retval DRV_TIMER_CAP_DIS
 * @retval DRV_TIMER_CAP_H2L
 * @retval DRV_TIMER_CAP_L2H
 * @retval DRV_TIMER_CAP_BOTH
 */
__STATIC_INLINE uint32_t DrvTimerGetCapEve(TimerTypedef* timer_instance) {
  return (uint32_t)READ_BIT(timer_instance->CONTROL, TMR_CONTROL_CAP_EVENT);
}

/**
 * @fn __STATIC_INLINE void DrvTimerSetMode(TimerTypedef* timer_instance, uint32_t mode)
 * @brief Set timer mode
 * 
 * @param[in] timer_instance Timer instance
 * @param[in] mode This parameter can be one of the following values:
 *            @arg @ref DRV_TIMER_FREE_RUN
 *            @arg @ref DRV_TIMER_USER_DEF
 */
__STATIC_INLINE void DrvTimerSetMode(TimerTypedef* timer_instance, uint32_t mode) {
  MODIFY_REG(timer_instance->CONTROL, TMR_CONTROL_MODE, mode);
}

/**
 * @fn __STATIC_INLINE uint32_t DrvTimerGetMode(TimerTypedef* timer_instance)
 * @brief Get timer mode
 * 
 * @param[in] timer_instance Timer instance
 * @return Mode can be one of the following values:
 * @retval DRV_TIMER_FREE_RUN
 * @retval DRV_TIMER_USER_DEF
 */
__STATIC_INLINE uint32_t DrvTimerGetMode(TimerTypedef* timer_instance) {
  return (uint32_t)READ_BIT(timer_instance->CONTROL, TMR_CONTROL_MODE);
}

/**
 * @fn __STATIC_INLINE void DrvTimerSetPwmTri(TimerTypedef* timer_instance, uint32_t trigger)
 * @brief Set pwm trigger
 * 
 * @param[in] timer_instance Timer instance
 * @param[in] trigger This parameter can be one of the following values:
 *            @arg @ref DRV_TIMER_NO_TRI
 *            @arg @ref DRV_TIMER_OF
 *            @arg @ref DRV_TIMER_OF_MAT
 *            @arg @ref DRV_TIMER_MAT
 */
__STATIC_INLINE void DrvTimerSetPwmTri(TimerTypedef* timer_instance, uint32_t trigger) {
  MODIFY_REG(timer_instance->CONTROL, TMR_CONTROL_PWM_TRG, trigger);
}

/**
 * @fn __STATIC_INLINE uint32_t DrvTimerGetPwmTri(TimerTypedef* timer_instance)
 * @brief Get pwm trigger
 * 
 * @param[in,out] timer_instance Timer instance
 * @return Trigger can be one of the following values:
 * @retval DRV_TIMER_NO_TRI
 * @retval DRV_TIMER_OF
 * @retval DRV_TIMER_OF_MAT
 * @retval DRV_TIMER_MAT
 */
__STATIC_INLINE uint32_t DrvTimerGetPwmTri(TimerTypedef* timer_instance) {
  return (uint32_t)(READ_BIT(timer_instance->CONTROL, TMR_CONTROL_PWM_TRG));
}

/**
 * @fn __STATIC_INLINE void DrvTimerSetPwmOutMode(TimerTypedef* timer_instance, uint32_t out_mode)
 * @brief Set pwm out mode
 * 
 * @param[in] timer_instance Timer instance
 * @param[in] out_mode This parameter can be one of the following values:
 *        @arg @ref DRV_TIMER_OUT_PLU
 *        @arg @ref DRV_TIMER_OUT_TOG
 */
__STATIC_INLINE void DrvTimerSetPwmOutMode(TimerTypedef* timer_instance, uint32_t out_mode) {
  MODIFY_REG(timer_instance->CONTROL, TMR_CONTROL_PULSE_TGL, out_mode);
}

/**
 * @fn __STATIC_INLINE uint32_t DrvTimerGetPwmOutMode(TimerTypedef* timer_instance)
 * @brief Get pwm out mode
 * 
 * @param[in] timer_instance Timer instance
 * @return Out mode can be one of the following values:
 * @retval DRV_TIMER_OUT_PLU
 * @retval DRV_TIMER_OUT_TOG
 */
__STATIC_INLINE uint32_t DrvTimerGetPwmOutMode(TimerTypedef* timer_instance) {
  return (uint32_t)(READ_BIT(timer_instance->CONTROL, TMR_CONTROL_PULSE_TGL));
}

/**
 * @fn __STATIC_INLINE void DrvTimerSetPolarity(TimerTypedef* timer_instance, uint32_t pola)
 * @brief Set polarity of pulse on PWM port
 * 
 * @param[in] timer_instance Timer instance
 * @param[in] pola This parameter can be one of the following values:
 *        @arg @ref DRV_TIMER_POS
 *        @arg @ref DRV_TIMER_NEG
 */
__STATIC_INLINE void DrvTimerSetPolarity(TimerTypedef* timer_instance, uint32_t pola) {
  MODIFY_REG(timer_instance->CONTROL, TMR_CONTROL_PWM_POL, pola);
}

/**
 * @fn __STATIC_INLINE uint32_t DrvTimerGetPolarity(TimerTypedef* timer_instance)
 * @brief Get polarity of pulse on PWM port
 * 
 * @param[in] timer_instance Timer instance
 * @return Polarity can be one of the following values:
 * @retval DRV_TIMER_POS
 * @retval DRV_TIMER_NEG
 */
__STATIC_INLINE uint32_t DrvTimerGetPolarity(TimerTypedef* timer_instance) {
  return (uint32_t)(READ_BIT(timer_instance->CONTROL, TMR_CONTROL_PWM_POL));
}

/**
 * @fn __STATIC_INLINE void DrvTimerEnable(TimerTypedef* timer_instance)
 * @brief Enable Timer
 * 
 * @param[in] timer_instance Timer instance
 */
__STATIC_INLINE void DrvTimerEnable(TimerTypedef* timer_instance) {
  SET_BIT(timer_instance->CONTROL, TMR_CONTROL_EN);
}

/**
 * @fn __STATIC_INLINE void DrvTimerDisable(TimerTypedef* timer_instance)
 * @brief Disable Timer
 * 
 * @param[in] timer_instance Timer instance
 */
__STATIC_INLINE void DrvTimerDisable(TimerTypedef* timer_instance) {
  CLEAR_BIT(timer_instance->CONTROL, TMR_CONTROL_EN);
}

/**
 * @fn __STATIC_INLINE uint32_t DrvTimerIsEnable(TimerTypedef* timer_instance)
 * @brief Check if timer is enabled
 * 
 * @param[in] timer_instance Timer instance
 * @return Timer enable statu
 */
__STATIC_INLINE uint32_t DrvTimerIsEnable(TimerTypedef* timer_instance) {
  return (uint32_t) (READ_BIT(timer_instance->CONTROL, TMR_CONTROL_EN) >> TMR_CONTROL_EN_Pos);
}

/** @} TIMER_DRV_EF_Configuration */

/**
 * @defgroup TIMER_DRV_EF_IT_Management TIMER Interrupt Management Exported Functions
 * @{
 */

/**
 * @fn __STATIC_INLINE void DrvTimerEnCapIrq(TimerTypedef* timer_instance)
 * @brief Enable capture Interrupt
 * 
 * @param[in] timer_instance Timer instance
 */
__STATIC_INLINE void DrvTimerEnCapIrq(TimerTypedef* timer_instance) {
  SET_BIT(timer_instance->IRQ_EN, TMR_IRQ_EN_CAP_INT_EN);
}

/**
 * @fn __STATIC_INLINE void DrvTimerDisCapIrq(TimerTypedef* timer_instance)
 * @brief Disnable capture Interrupt
 * 
 * @param[in] timer_instance Timer instance
 */
__STATIC_INLINE void DrvTimerDisCapIrq(TimerTypedef* timer_instance) {
  CLEAR_BIT(timer_instance->IRQ_EN, TMR_IRQ_EN_CAP_INT_EN);
}

/**
 * @fn __STATIC_INLINE uint32_t DrvTimerIsCapIrq(TimerTypedef* timer_instance)
 * @brief If capture Interrupt is enabled
 * 
 * @param[in] timer_instance Timer instance
 * @return interrupt status:
 * @retval 1 Enable
 * @retval 0 Disable 
 */
__STATIC_INLINE uint32_t DrvTimerIsCapIrq(TimerTypedef* timer_instance) {
  return (uint32_t) (READ_BIT(timer_instance->IRQ_EN, TMR_IRQ_EN_CAP_INT_EN) >> TMR_IRQ_EN_CAP_INT_EN_Pos);
}


/**
 * @fn __STATIC_INLINE void DrvTimerEnOvfIrq(TimerTypedef* timer_instance)
 * @brief Enable overflow Interrupt
 * 
 * @param[in] timer_instance Timer instance
 */
__STATIC_INLINE void DrvTimerEnOvfIrq(TimerTypedef* timer_instance) {
  SET_BIT(timer_instance->IRQ_EN, TMR_IRQ_EN_OVF_INT_EN);
}

/**
 * @fn __STATIC_INLINE void DrvTimerDisOvfIrq(TimerTypedef* timer_instance)
 * @brief Disnable overflow Interrupt
 * 
 * @param[in] timer_instance Timer instance
 */
__STATIC_INLINE void DrvTimerDisOvfIrq(TimerTypedef* timer_instance) {
  CLEAR_BIT(timer_instance->IRQ_EN, TMR_IRQ_EN_OVF_INT_EN);
}

/**
 * @fn __STATIC_INLINE uint32_t DrvTimerIsOvfIrq(TimerTypedef* timer_instance)
 * @brief If overflow Interrupt is enabled
 * 
 * @param[in] timer_instance Timer instance
 * @return interrupt status:
 * @retval 1 Enable
 * @retval 0 Disable
 */
__STATIC_INLINE uint32_t DrvTimerIsOvfIrq(TimerTypedef* timer_instance) {
  return (uint32_t) (READ_BIT(timer_instance->IRQ_EN, TMR_IRQ_EN_OVF_INT_EN) >> TMR_IRQ_EN_OVF_INT_EN_Pos);
}

/**
 * @fn __STATIC_INLINE void DrvTimerEnMatIrq(TimerTypedef* timer_instance)
 * @brief Enable match Interrupt
 * 
 * @param[in] timer_instance Timer instance
 */
__STATIC_INLINE void DrvTimerEnMatIrq(TimerTypedef* timer_instance) {
  SET_BIT(timer_instance->IRQ_EN, TMR_IRQ_EN_MAT_INT_EN);
}

/**
 * @fn __STATIC_INLINE void DrvTimerDisMatIrq(TimerTypedef* timer_instance)
 * @brief Disnable match Interrupt
 * 
 * @param[in] timer_instance Timer instance
 */
__STATIC_INLINE void DrvTimerDisMatIrq(TimerTypedef* timer_instance) {
  CLEAR_BIT(timer_instance->IRQ_EN, TMR_IRQ_EN_MAT_INT_EN);
}

/**
 * @fn __STATIC_INLINE uint32_t DrvTimerIsMatIrq(TimerTypedef* timer_instance)
 * @brief If match Interrupt is enabled
 * 
 * @param[in] timer_instance Timer instance
 * @return interrupt status:
 * @retval 1 Enable
 * @retval 0 Disable 
 */
__STATIC_INLINE uint32_t DrvTimerIsMatIrq(TimerTypedef* timer_instance) {
  return (uint32_t) (READ_BIT(timer_instance->IRQ_EN, TMR_IRQ_EN_MAT_INT_EN) >> TMR_IRQ_EN_MAT_INT_EN_Pos);
}

/** @} TIMER_DRV_EF_IT_Management */


/**
 * @defgroup TIMER_DRV_EF_Init TIMER Initialization and De-initialization Exported Functions
 * @{
 */

/**
 * @fn ErrorStatus DrvTimerDeInit(TimerTypedef* timer_instance)
 * @brief De-initialize TIMER registers
 * 
 * @param[in] timer_instance TIMER instance
 * @return TIMER is de-initialized or not
 * @retval kSuccess TIMER registers are de-initialized
 * @retval kError TIMER registers are not de-initialized
 */
ErrorStatus DrvTimerDeInit(TimerTypedef* timer_instance);

/**
 * @fn ErrorStatus DrvTimerInit(TimerTypedef* timer_instance, DrvTimerInitTypedef* timer_init_struct)
 * @brief Initialize TIMER registers according to the specified parameters in DrvTimerInitTypedef
 * 
 * @param[in] timer_instance TIMER instance
 * @param[in] timer_init_struct pointer to a DrvTimerInitTypedef structure that contians the 
 *            configuration information for the specified TIMER peripheral 
 * @return TIMER is initialized or not
 * @retval kSuccess TIMER registers are initialized according to timer_init_struct content
 * @retval kError Problem occured during TIMER registers initialization
 */
ErrorStatus DrvTimerInit(TimerTypedef* timer_instance, DrvTimerInitTypedef* timer_init_struct);

/**
 * @fn void DrvTimerStructInit(DrvTimerInitTypedef* timer_init_struct, uint32_t value)
 * @brief Set each @ref DrvTimerInitTypedef field to default value
 * 
 * @param[out] timer_init_struct pointer to a @ref DrvTimerInitTypedef structure
 *             whose field will be set to default values
 * @param[in]  value timer value
 */
void DrvTimerStructInit(DrvTimerInitTypedef* timer_init_struct, uint32_t value);

/** @} TIMER_DRV_EF_Init */
/** @} TIMER_DRV_Exported_Functions */
/** @} TIMER_DRV */
/** @} GT9881_Drivers */

#ifdef __cplusplus
}
#endif /* __cplusplus */

#endif /* GT98XX_DRIVER_GT98XX_DRV_TIMER_H_ */
